package com.magicstone.common.Time;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public final class TimeUtil {
	private final static Log logger = LogFactory.getLog(TimeUtil.class);

	public static Float getAge(Date birth, Date now){
		long day = 0;
		if(null != birth && null != now){
			Calendar cal = Calendar.getInstance();
			cal.setTime(birth);

			long l_birth = cal.getTimeInMillis();
			cal.setTime(now);
			long l_now = cal.getTimeInMillis();
			day = (l_now - l_birth) / (1000  * 60 * 60 * 24) + 1;
		}
		return day / 365f;
	}
	/*
	 * 获取指定月份上旬的起始时间
	 * @param year年份
	 * @param month月份1~12
	 * @return 上旬开始时间
	 */
	public static Date getFirstTenBegining(Integer year, Integer month) {
		Date date = null;
		if (null != year && null != month && (0 < month) && (month < 13)) {
			Calendar cal = Calendar.getInstance();// 获取当天日期
			cal.set(year, month - 1, 1, 0, 0, 0);
			date = cal.getTime();
		}
		return date;
	}

	public static Date getFirstTenBegining(Date now) {
		Date date = null;
		if (null != now) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(now);
			date = getFirstTenBegining(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH ) + 1);
		}
		return date;
	}

	/*
	 * 获取指定月份上旬的结束时间
	 * @param year年份
	 * @param month月份
	 * @return 上旬开始时间
	 */
	public static Date getFirstTenEnding(Integer year, Integer month) {
		Date date = null;
		if (null != year && null != month && (0 < month) && (month < 13)) {
			Calendar cal = Calendar.getInstance();// 获取当天日期
			cal.set(year, month - 1, 10, 23, 59, 59);
			date = cal.getTime();
		}
		return date;
	}

	public static Date getFirstTenEnding(Date now) {
		Date date = null;
		if (null != now) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(now);
			date = getFirstTenEnding(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH ) + 1);
		}
		return date;
	}

	/*
	 * 获取指定月份中旬的起始时间
	 * @param year年份
	 * @param month月份
	 * @return 中旬开始时间
	 */
	public static Date getSecondTenBegining(Integer year, Integer month) {
		Date date = null;
		if (null != year && null != month && (0 < month) && (month < 13)) {
			Calendar cal = Calendar.getInstance();// 获取当天日期
			cal.set(year, month - 1, 11, 0, 0, 0);
			date = cal.getTime();
		}
		return date;
	}

	public static Date getSecondTenBegining(Date now) {
		Date date = null;
		if (null != now) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(now);
			date = getSecondTenBegining(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH ) + 1);
		}
		return date;
	}

	/*
	 * 获取指定月份中旬的结束时间
	 * @param year年份
	 * @param month月份
	 * @return 中旬结束时间
	 */
	public static Date getSecondTenEnding(Integer year, Integer month) {
		Date date = null;
		if (null != year && null != month && (0 < month) && (month < 13)) {
			Calendar cal = Calendar.getInstance();// 获取当天日期
			cal.set(year, month - 1, 20, 23, 59, 59);
			date = cal.getTime();
		}
		return date;
	}

	public static Date getSecondTenEnding(Date now) {
		Date date = null;
		if (null != now) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(now);
			date = getSecondTenEnding(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH ) + 1);
		}
		return date;
	}

	/*
	 * 获取指定月份下旬的起始时间
	 * @param year年份
	 * @param month月份
	 * @return 下旬开始时间
	 */
	public static Date getThirdTenBegining(Integer year, Integer month) {
		Date date = null;
		if (null != year && null != month && (0 < month) && (month < 13)) {
			Calendar cal = Calendar.getInstance();// 获取当天日期
			cal.set(year, month - 1, 21, 0, 0, 0);
			date = cal.getTime();
		}
		return date;
	}

	public static Date getThirdTenBegining(Date now) {
		Date date = null;
		if (null != now) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(now);
			date = getThirdTenBegining(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH ) + 1);
		}
		return date;
	}

	/*
	 * 获取指定月份下旬的结束时间
	 * @param year年份
	 * @param month月份,从1开始
	 * @return 下旬结束时间
	 */
	public static Date getThirdTenEnding(Integer year, Integer month) {
		Date date = null;
		if (null != year && null != month && (0 < month) && (month < 13)) {
			Calendar cal = Calendar.getInstance();// 获取当天日期
			cal.set(year, month - 1, 1);
			int num = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
			cal.set(year, month - 1, num, 23, 59, 59);
			date = cal.getTime();
		}
		return date;
	}

	public static Date getThirdTenEnding(Date now) {
		Date date = null;
		if (null != now) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(now);
			date = getThirdTenEnding(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH ) + 1);
		}
		return date;
	}

	public static String toLocalDate(Date date) {
		try {
			Calendar cal = Calendar.getInstance();// 获取当天日期
			cal.setTime(date);
			return cal.get(Calendar.YEAR) + "-" + (cal.get(Calendar.MONTH) + 1)
					+ "-" + cal.get(Calendar.DAY_OF_MONTH);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return "";
	}
	
	public static String toDateAlign(Date date) {
		String time = "";
		try {
			Calendar cal = Calendar.getInstance();// 获取当天日期
			cal.setTime(date);
			time += cal.get(Calendar.YEAR) + "-";
			time += (cal.get(Calendar.MONTH) + 1) < 10 ? "0"
					+ (cal.get(Calendar.MONTH) + 1)
					: cal.get(Calendar.MONTH) + 1;
			time += "-";
			time += (cal.get(Calendar.DAY_OF_MONTH) < 10) ? "0"
					+ (cal.get(Calendar.DAY_OF_MONTH)) : cal
					.get(Calendar.DAY_OF_MONTH);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return time;
	}

	public static String toLocalDatetime(Date date) {
		try {
			Calendar cal = Calendar.getInstance();// 获取当天日期
			cal.setTime(date);
			return cal.get(Calendar.YEAR) + "-" + (cal.get(Calendar.MONTH) + 1)
					+ "-" + cal.get(Calendar.DAY_OF_MONTH) + " "
					+ cal.get(Calendar.HOUR_OF_DAY) + ":"
					+ cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return "";
	}

	public static String toLocalTime(Date date) {
		String time = "";
		try {
			Calendar cal = Calendar.getInstance();// 获取当天日期
			cal.setTime(date);
			time += cal.get(Calendar.YEAR) + "年";
			time += (cal.get(Calendar.MONTH) + 1) < 10 ? "0"
					+ (cal.get(Calendar.MONTH) + 1)
					: cal.get(Calendar.MONTH) + 1;
			time += "月";
			time += (cal.get(Calendar.DAY_OF_MONTH) < 10) ? "0"
					+ (cal.get(Calendar.DAY_OF_MONTH)) : cal
					.get(Calendar.DAY_OF_MONTH);
			time += "日 ";
			time += (cal.get(Calendar.HOUR_OF_DAY) < 10) ? "0"
					+ cal.get(Calendar.HOUR_OF_DAY) : cal
					.get(Calendar.HOUR_OF_DAY);
			time += "时 ";
			time += (cal.get(Calendar.MINUTE) < 10) ? "0"
					+ cal.get(Calendar.MINUTE) : cal.get(Calendar.MINUTE);
			time += "分";
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return time;
	}

	public static Date getMonthStartDatetime(Date now) {
		Date date = null;
		if (null != now) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(now);
			int num = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
			cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 1, 0, 0, 0);
			date = cal.getTime();
		}
		return date;
	}
	
	/*
	 * Get the start time of the specified month.
	 * @param year
	 * @param month start from 1.
	 * @return the start time of the specified month.
	 */
	public static Date getMonthStartDatetime(int year, int month) {
		Date date = null;
		try{
			month = month < 1 ? 1 : month;
			month = month > 12 ? 12 : month;
			Calendar cal = Calendar.getInstance();
			cal.set(year, month - 1, 1, 0, 0, 0);
			date = cal.getTime();
		}catch(Exception e){
			logger.debug(e.getMessage());
		}
		return date;
	}
	public static Date getYearStartDatetime(int year) {
		Date date = null;
		try{
			Calendar cal = Calendar.getInstance();
			cal.set(year, 0, 1, 0, 0, 0);
			date = cal.getTime();
		}catch(Exception e){
			logger.debug(e.getMessage());
		}
		return date;
	}

	public static Date getMonthEndDatetime(Date now) {
		Date date = null;
		if (null != now) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(now);
			int num = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
			cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), num,
					23, 59, 59);
			date = cal.getTime();
		}
		return date;
	}
	public static Date getMonthEndDatetime(int year, int month) {
		Date date = null;
		
		try{
			month = month < 1 ? 1 : month;
			month = month > 12 ? 12 : month;
			Calendar cal = Calendar.getInstance();
			cal.clear();
			cal.set(Calendar.YEAR, year);
			cal.set(Calendar.MONTH, month - 1);
			int num = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
			cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), num, 23, 59, 59);
			date = cal.getTime();
		}catch(Exception e){
			logger.debug(e.getMessage());
		}
		return date;
	}
	public static Date getYearEndDatetime(int year) {
		Date date = null;
		
		try{
			Calendar cal = Calendar.getInstance();
			cal.clear();
			cal.set(Calendar.YEAR, year);
			cal.set(Calendar.MONTH, 11);
			int num = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
			cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), num, 23, 59, 59);
			date = cal.getTime();
		}catch(Exception e){
			logger.debug(e.getMessage());
		}
		return date;
	}
	
	public static Xiong getPrevXiong(Date now){
		Xiong result = null;
		if (null != now) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(now);
			Integer xiong = cal.get(Calendar.DAY_OF_MONTH) / 10;
			switch(xiong){
			case 0:	//上旬
				if(cal.get(Calendar.MONTH) == 0){
					result = new Xiong(cal.get(Calendar.YEAR) - 1, 12, 3);
				}else{
					result = new Xiong(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 3);
				}
				break;
			case 1:
			case 2:
				result = new Xiong(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, xiong);
				break;
			case 3:
				result = new Xiong(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, 2);
				break;
			}
		}
		return result;
	}
	
	public static List<Day> generateDays(Date now, int n){
		List<Day> days = new ArrayList<Day>();
		Calendar calendar =Calendar.getInstance();  
		calendar.setTime(now);
		calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - n + 1);
		for(int i = 0; i < n; i++){
			days.add(new Day(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH)));
			calendar.add(Calendar.DATE, 1);
		}
		
		return days;
	}
	
	public static List<Day> generateDays(Date from, Date to){
		List<Day> days = new ArrayList<Day>();
		if(from != null && to != null){
			
			if(!to.after(from)){
				Date temp = from;
				from = to;
				to = temp;
			}
			Calendar calFrom = Calendar.getInstance();
			Calendar calTo = Calendar.getInstance();
			calFrom.setTime(from);
			calTo.setTime(to);
			while(calTo.after(calFrom)){
				days.add(new Day(calFrom.get(Calendar.YEAR), calFrom.get(Calendar.MONTH) + 1, calFrom.get(Calendar.DAY_OF_MONTH)));
				calFrom.add(Calendar.DATE, 1);
			}
			days.add(new Day(calTo.get(Calendar.YEAR), calTo.get(Calendar.MONTH) + 1, calTo.get(Calendar.DAY_OF_MONTH)));
			
			/////////////////////////放弃自己的时间序列算法2012-1-2
			/*
			for(int year = calFrom.get(Calendar.YEAR); year <= calTo.get(Calendar.YEAR); year++){
				int minMonth = (year != calFrom.get(Calendar.YEAR)) ? 0 : calFrom.get(Calendar.MONTH);
				int maxMonth = (year != calTo.get(Calendar.YEAR)) ? 11 : calTo.get(Calendar.MONTH);
				System.out.println("1----[" + year + ":" + minMonth + ",(" + calFrom.get(Calendar.MONTH) + "), " + maxMonth + "(" + calTo.get(Calendar.MONTH) + ")]");
				for(int month = minMonth; month <= maxMonth ; month++){
					Integer maxDay = null;
					Integer minDay = null;
					if(year == calTo.get(Calendar.YEAR)){//同一年
						minDay = (month != calFrom.get(Calendar.MONTH)) ? 1 : calFrom.get(Calendar.DAY_OF_MONTH);
						System.out.println("2-------" + year + ":" + month + ":" + getMaxDayOfMonth(year, month));
						maxDay = (month != calTo.get(Calendar.MONTH)) ? getMaxDayOfMonth(year, month) : calTo.get(Calendar.DAY_OF_MONTH);
					}else{
						minDay = 1;
						maxDay = getMaxDayOfMonth(year, month);
					}

					System.out.println("3------(" + year + "-" + month + ":" + minDay + "," + maxDay + ")");
					for(int k = minDay; k <= maxDay; k++){
						System.out.println("^^^^^^^^^^^^" + year + "-" + month + "-" + k);
						days.add(new Day(year, month + 1, k));
					}
				}
				
			}*/
		}
		return days;
	}
	
	public static List<Day> generateDays(Day from, Day to){
		List<Day> days = new ArrayList<Day>();
		if(from != null && to != null){
			
			Calendar calFrom = Calendar.getInstance();
			Calendar calTo = Calendar.getInstance();
			calFrom.set(from.getYear(), from.getMonth() - 1, from.getDay());
			calTo.set(to.getYear(), to.getMonth() - 1, to.getDay());
			days = generateDays(calFrom.getTime(), calTo.getTime());
		}
		return days;
	}
	public static List<Xiong> generateXiongs(Date from, Date to){
		List<Xiong> xiongs = new ArrayList<Xiong>();
		if(from != null && to != null){
			
			if(!to.after(from)){
				Date temp = from;
				from = to;
				to = temp;
			}
			Calendar calFrom = Calendar.getInstance();
			Calendar calTo = Calendar.getInstance();
			calFrom.setTime(from);
			calTo.setTime(to);
			for(int year = calFrom.get(Calendar.YEAR); year <= calTo.get(Calendar.YEAR); year++){
				int minMonth = (year != calFrom.get(Calendar.YEAR)) ? 0 : calFrom.get(Calendar.MONTH);
				int maxMonth = (year != calTo.get(Calendar.YEAR)) ? 11 : ((calTo.get(Calendar.MONTH) > 0) ? (calTo.get(Calendar.MONTH) - 1) : 0);
				//System.out.println("----(" + year + ":" + minMonth + "," + maxMonth + ")");
				for(int month = minMonth; month <= maxMonth ; month++){
					for(int k = 0; k < 3; k++){
						//System.out.println("------------" + year + "-" + month + "-" + k);
						xiongs.add(new Xiong(year, month + 1, k + 1));
					}
				}
			}
		}
		return xiongs;
	}
	
	/*
	 * The month begin with 0.
	 */
	public static List<Month> generateMonths(Date from, Date to){
		List<Month> months = new ArrayList<Month>();
		if(from != null && to != null){
			if(!to.after(from)){
				Date temp = from;
				from = to;
				to = temp;
			}
			Calendar calFrom = Calendar.getInstance();
			Calendar calTo = Calendar.getInstance();
			calFrom.setTime(from);
			calTo.setTime(to);
			int fromYear = calFrom.get(Calendar.YEAR);
			int fromMonth = calFrom.get(Calendar.MONTH);
			int toYear = calTo.get(Calendar.YEAR);
			int toMonth = calTo.get(Calendar.MONTH);
			for(int year = fromYear; year <= toYear; year++){
				int minMonth = (year != fromYear) ? 0 : fromMonth;
				int maxMonth = (year != toYear) ? 11 : toMonth;
				//System.out.println("----(" + year + ":" + minMonth + "," + maxMonth + ")");
				for(int month = minMonth; month <= maxMonth; month++){
					months.add(new Month(year, month));
				}
				logger.debug("Current year:" + year + "Min-month is:" + minMonth + "   Max-month is :" + maxMonth + "(" + year + "=== from:" + fromYear + "." + fromMonth + ", to:" + toYear + "." + toMonth + ")");
			}
		}
		return months;
	}
	public static List<Year> generateYears(Date from, Date to){
		List<Year> years = new ArrayList<Year>();
		if(from != null && to != null){
			if(!to.after(from)){
				Date temp = from;
				from = to;
				to = temp;
			}
			Calendar calFrom = Calendar.getInstance();
			Calendar calTo = Calendar.getInstance();
			calFrom.setTime(from);
			calTo.setTime(to);
			for(int year = calFrom.get(Calendar.YEAR); year <= calTo.get(Calendar.YEAR); year++){
				years.add(new Year(year));
			}
		}
		return years;
	}
	
	/*
	 * 0 < month < 13
	 */
	public static Integer getMaxDayOfMonth(Integer year, Integer month){
		Integer maxDay = null;
		if (null != year && null != month && (0 <= month) && (month < 12)) {
			Calendar cal = Calendar.getInstance();// 获取当天日期
			cal.set(year, month, 1);
			maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
		}
		return maxDay;
	}
	
	public static Date generateDayBegin(Day day){
		Calendar cal = Calendar.getInstance();
		cal.set(day.getYear(), day.getMonth() - 1, day.getDay(), 0, 0, 1);
		return cal.getTime();
	}
	
	public static Date generateDayEnd(Day day){
		Calendar cal = Calendar.getInstance();
		cal.set(day.getYear(), day.getMonth() - 1, day.getDay(), 23, 59, 59);
		return cal.getTime();	
	}
	
	/*
	 * 获取指定日期前n天的日期
	 */
	public static Date getDateBefore(Date day,int n){  
	   Calendar now =Calendar.getInstance();  
	   now.setTime(null != day ? day : new Date());  
	   now.set(Calendar.DATE, now.get(Calendar.DATE)-n);  
	   return now.getTime();  
	} 
	
	public static Day getCurrentXiongBegin(){
		Date result = null;
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date());
		switch((cal.get(Calendar.DAY_OF_MONTH) - 1) / 10){
			case 0:
				result = getFirstTenBegining(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1);
				break;
			case 1:
				result = getSecondTenBegining(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1);
				break;
			case 2:
			case 3:
				result = getThirdTenBegining(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1);
				break;
		}
		return new Day(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
	}
	
	public static Day getCurrentXiongEnd(){
		Date result = null;
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date());
		switch((cal.get(Calendar.DAY_OF_MONTH) - 1) / 10){
			case 0:
				result = getFirstTenEnding(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1);
				break;
			case 1:
				result = getSecondTenEnding(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1);
				break;
			case 2:
			case 3:
				result = getThirdTenEnding(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1);
				break;
		}
		cal.setTime(result);
		return new Day(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
	}

	public static Day getXiongBegin(Integer year, Integer month, Integer xiong){
		Date result = null;;
		switch(xiong){
			case 1:
				result = getFirstTenBegining(year, month);
				break;
			case 2:
				result = getSecondTenBegining(year, month);
				break;
			case 3:
				result = getThirdTenBegining(year, month);
				break;
		}
		if(result != null){
			Calendar cal = Calendar.getInstance();
			cal.setTime(result);
			return new Day(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
		}
		return null;
	}
	
	public static Date getXiongStartDatetime(Integer year, Integer month, Integer xiong){
		Date result = null;;
		switch(xiong){
			case 1:
				result = getFirstTenBegining(year, month);
				break;
			case 2:
				result = getSecondTenBegining(year, month);
				break;
			case 3:
				result = getThirdTenBegining(year, month);
				break;
		}

		return result;
	}
	public static Day getXiongEnd(Integer year, Integer month, Integer xiong){
		Date result = null;;
		switch(xiong){
			case 1:
				result = getFirstTenEnding(year, month);
				break;
			case 2:
				result = getSecondTenEnding(year, month);
				break;
			case 3:
				result = getThirdTenEnding(year, month);
				break;
		}
		if(result != null){
			Calendar cal = Calendar.getInstance();
			cal.setTime(result);
			return new Day(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
		}
		return null;
	}

	public static Date getXiongEndDatetime(Integer year, Integer month, Integer xiong){
		Date result = null;;
		switch(xiong){
			case 1:
				result = getFirstTenEnding(year, month);
				break;
			case 2:
				result = getSecondTenEnding(year, month);
				break;
			case 3:
				result = getThirdTenEnding(year, month);
				break;
		}
		return result;
	}
	public static Integer getXiongIndex(Date now){
		Integer result = null;
		Calendar cal = Calendar.getInstance();
		cal.setTime(now);
		switch((cal.get(Calendar.DAY_OF_MONTH) - 1) / 10){
			case 0:
				result = 1;
				break;
			case 1:
				result = 2;
				break;
			case 2:
			case 3:
				result = 3;
				break;
		}
		return result;
	}
	
	public static String xiong2String(Integer xiong){
		String xiongName = "错误时间";
		switch(xiong){
		case 1:
			xiongName = "上";
			break;
		case 2:
			xiongName = "中";
			break;
		case 3:
			xiongName = "下";
			break;
		}
		return xiongName;
	}
}
